﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Numerics;

namespace RSA
{
    public partial class Form1 : Form
    {
        String Open, Save, Open2, Save2;
        public static Boolean b1, b2;
        //Show show1, show2;
        private BigInteger n,d,E,p,q,fn;
        private int[] bytemasukan;
        private BigInteger[] hasilbyte;
        String result = "";


        public Form1()
        {
            InitializeComponent();
            radioButton1.Checked = true;
            Open = "";
            Save = "";
            Open2 = "";
            Save2 = "";
            b1 = false;
            b2 = false;
        }

        public void kunci()
        {
            n = p * q;
            fn = (p - 1) * (q - 1);
            d = (1 / E) % fn;
        }

        public BigInteger get_public_key()
        {
            return E;
        }

        public BigInteger get_private_key()
        {
            return d;
        }

        public BigInteger panjang_blok(BigInteger n)
        {
            return (BigInteger.Divide(n,BigInteger.Parse("256")));
        }


        public String enkripsi(string s)
        {
            int i;
            BigInteger potongan = 0;
            BigInteger temp = 0;
            String hasil = "";
            int panjang = (int)panjang_blok(n);
            //int j = 0;
            
            for (i = 0; i < s.Length; i++)
            {
                potongan = potongan * 256 + s[i];
                if ((i % panjang) == panjang - 1)
                {
                    temp = Pangkat(potongan, E, n);
                    hasil += temp;
                    potongan = 0;
                    //hasilbyte[j] = temp;
                    //j++;
                }
            }
            if ((i%panjang) < panjang-1)
            {
                temp = Pangkat(potongan, E, n);
                hasil += temp;
                //hasilbyte[j] = temp;
                //j++;
            }
            return hasil;
        }

        public String dekripsi(string s)
        {
            int i;
            BigInteger potongan = 0;
            BigInteger temp = 0;
            String hasil = "";
            int panjang = (int)panjang_blok(n);
            int j = 0;

            for (i = 0; i < s.Length; i++)
            {
                potongan = potongan * 256 + s[i];
                if ((i % panjang) == panjang - 1)
                {
                    temp = Pangkat(potongan, d, n);
                    hasil += temp;
                    potongan = 0;
                    //hasilbyte[j] = temp;
                    //j++;
                }
            }
            if ((i % panjang) < panjang - 1)
            {
                temp = Pangkat(potongan, d, n);
                hasil += temp;
                //hasilbyte[j] = temp;
                //j++;
            }
            return hasil;
        }


        private String open(int kode)
        {
            Stream myStream = null;
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.InitialDirectory = "c:\\";
            //openFileDialog1.Filter = "pri files (*.pri)|*.pri|pub files (*.pub)|*.pub|txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 4;
            openFileDialog1.RestoreDirectory = true;
            //String result = "";
            int c;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if ((myStream = openFileDialog1.OpenFile()) != null)
                    {
                        if (kode == 1)
                            textBox5.Text = openFileDialog1.FileName;
                        else
                            textBox1.Text = openFileDialog1.FileName;
                        using (myStream)
                        {
                            int i=0;
                            // Insert code to read the stream here.
                            while ((c = myStream.ReadByte()) != -1)
                            {
                                //bytemasukan[i] = c;
                                result += (char)c;
                                //i++;
                            }
                            MessageBox.Show("Error: Could not read file from disk. Original error: " + result.Length);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
            return result;
        }

        private void save(String s)
        {
            Stream myStream;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();

            saveFileDialog1.InitialDirectory = "c:\\";
            saveFileDialog1.Filter = "pri files (*.pri)|*.pri|pub files (*.pub)|*.pub|txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 4;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog1.OpenFile()) != null)
                {
                    // Code to write the stream goes here.
                    int i, l = s.Length;
                    for (i = 0; i < l; ++i)
                        myStream.WriteByte((Byte)s[i]);
                    myStream.Close();
                }
            }
        }

        private void savebyte(BigInteger[] masukan)
        {
            Stream myStream;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            byte[] bytearray;

            saveFileDialog1.InitialDirectory = "c:\\";
            saveFileDialog1.Filter = "pri files (*.pri)|*.pri|pub files (*.pub)|*.pub|txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 4;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog1.OpenFile()) != null)
                {
                    // Code to write the stream goes here.
                    int i, l = masukan.Length;
                    for (i = 0; i < l; ++i)
                    {
                        bytearray = masukan[i].ToByteArray();
                        for (int j = 0; j < bytearray.Length; ++j)
                            myStream.WriteByte((Byte)bytearray[j]);
                    }
                    myStream.Close();
                }
            }
        }

        private void cek1(object sender, EventArgs e)
        {
            if (radioButton1.Checked)
            {
                button7.Text = "Generate";
                textBox3.Visible = true;
                label3.Text = "E";
                label4.Text = "Private Key";
                label5.Text = "Public Key";
                Open = "";
                Save = "";
                Open2 = "";
                Save2 = "";
            }
        }

        private void cek2(object sender, EventArgs e)
        {
            if (radioButton2.Checked)
            {
                label3.Text = "";
                label4.Text = "Plaintext";
                label5.Text = "Ciphertext";
                textBox3.Visible = false;
                button1.Text = "Open";
                button4.Text = "Save";
                button7.Text = "Encrpyt";
                Open = "";
                Save = "";
                Open2 = "";
                Save2 = "";
            }
        }

        private void cek3(object sender, EventArgs e)
        {
            if (radioButton3.Checked)
            {
                label3.Text = "";
                label4.Text = "Plaintext";
                label5.Text = "Ciphertext";
                textBox3.Visible = false;
                button4.Text = "Open";
                button1.Text = "Save";
                button7.Text = "Decrypt";
                Open = "";
                Save = "";
                Open2 = "";
                Save2 = "";
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.Text == "Open")
            {
                Open = open(1);
            }
            else
            {
                MessageBox.Show("Pesan save : " + Save);
                save(Save);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (button4.Text == "Open")
            {
                Open2 = open(2);
            }
            else
            {
                Save2 = "save cipherteks";
                MessageBox.Show("Pesan save : " + Save2);
                save(Save2);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (!b1)
            {
                b1 = true;
                if (label4.Text == "Private Key")
                    show1 = new Show(3);
                else
                    show1 = new Show(1);
                if (button1.Text == "Open")
                    show1.showinfo(Open);
                else
                    show1.showinfo(Save);
                show1.Visible = true;
            }
            else
            {
                if (label4.Text == "Private Key")
                    show1.Kode = 3;
                else
                    show1.Kode = 1;
                if (button1.Text == "Open")
                    show1.showinfo(Open);
                else
                    show1.showinfo(Save);
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (!b2)
            {
                b2 = true;
                if (label5.Text == "Public Key")
                    show2 = new Show(4);
                else
                    show2 = new Show(2);
                if (button4.Text == "Open")
                    show2.showinfo(Open2);
                else
                    show2.showinfo(Save2);
                show2.Visible = true;
            }
            else
            {
                if (label5.Text == "Public Key")
                    show2.Kode = 4;
                else
                    show2.Kode = 2;
                if (button4.Text == "Open")
                    show2.showinfo(Open2);
                else
                    show2.showinfo(Save2);
            }
        }

        private BigInteger Pangkat(BigInteger angka, BigInteger pangkat, BigInteger mod)
        {
            if (pangkat == 0)
            {
                if (angka == 0)
                    return 0;
                else
                    return 1;
            }
            else
            {
                BigInteger hasil;
                hasil = Pangkat(angka, pangkat/2, mod);
                if (pangkat.IsEven)
                    return (hasil * hasil)%mod;
                else
                    return (hasil * hasil * angka)%mod;
            }
        }

        private BigInteger getInt(String s)
        {
            int i, l = s.Length;
            BigInteger hasil = 0;
            for (i = 0; i < l; ++i)
                hasil = hasil*10 + (((int)s[i]) - 48);
            return hasil;
        }

        private void button7_Click(object sender, EventArgs e)
        {
            p = getInt(textBox1.Text);
            q = getInt(textBox2.Text);
            E = getInt(textBox3.Text);
            kunci();
            MessageBox.Show("Bilangan inputan : " + p + ", " + q + ", dan " + E);
            MessageBox.Show("Hasilnya " + Pangkat(p, q, E));
            MessageBox.Show("Kunci Publik : " + E + " dan " + n);
            MessageBox.Show("Kunci Privat : " + Pangkat(E, fn-1, fn) + " dan " + n);
            String enkrip = enkripsi(result);
            MessageBox.Show("enkripnya " + enkrip);
            String dekrip = dekripsi(enkrip);
            MessageBox.Show("dekripnya " + dekrip);

        }

        private void button5_Click(object sender, EventArgs e)
        {
           textBox4.Text = open(1);
        }
    }
}
